/*
 * 客户端节点每个监控项的消息事件同步机制
 * Copyright (C) 2009  YuLicheng
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.sysmo.server.node.item;

import org.sysmo.communication.CommunicationProtocol;
import org.w3c.dom.Document;

/**
 *
 * 客户端节点每个监控项的消息事件同步机制处理类。使用此类可对客户端通信同步。
 *
 * @author YuLicheng
 */
public class ItemEvent {
    /**
     * XML文档对象。
     */
    public Document messageDocument;
    private Boolean[] eventList;
    private Object eventOK;

    /**
     * 创建新的事件处理类。
     */
    public ItemEvent() {
        eventOK = new Object();
        eventList = new Boolean[CommunicationProtocol.CLIENT_EVENT_NUMBER];
        for (int i = 0; i < eventList.length; i++) {
            eventList[i] = new Boolean(false);
        }
    }

    /**
     * 等待指定类型的消息。
     *
     * @param event 要等待的消息类型。
     */
    public void waitEvent(int event) {
        if (event < 0 || event >= eventList.length) {
            return;
        }
        eventList[event] = true;
        try {
            eventList[event].wait();
        } catch (Exception e) {
            e.printStackTrace();
        }
        eventList[event] = false;
    }

    /**
     * 退出消息处理。当等待的某个消息处理完成后，必须调用此方法以结束消息处理。
     */
    public void exitEvent() {
        eventOK.notify();
    }


    /**
     * 处理客户端节点发送的事件。客户端节点对象负责对客户端发送的消息进行监听，然后
     * 将消息转发给对应的监控项对象。监控项对象在此对消息进行处理，若有相应的线程正
     * 在等待对应的消息则唤醒该线程，并且等待其处理完毕，若没有线程等待此消息则忽略。
     * 客户端节点对象在调用此方法后不会再对消息进行监听，此时只有当前的监控项对象独
     * 占客户端的通讯接口。
     *
     * @param messageDocument 消息文档对象。
     * @param request 消息类型号。
     */
    public void doNodeMessage(Document messageDocument, int request) {
        if (request < 0 || request >= eventList.length || !eventList[request]) {
            return;
        }
        this.messageDocument = messageDocument;
        eventList[request].notify();
        try {
            eventOK.wait();
        } catch (Exception e) {
            e.printStackTrace();
        }
        eventList[request] = false; //double check
        this.messageDocument = null;
    }
}
